/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2020年8月22日
 */
package com.massyframework.beanskin.service;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

import com.massyframework.beanskin.Module;

/**
 * 服务仓储
 * 
 * <p>
 * 服务仓储管理在插件、装配件和片段之间共享的服务。
 * @author huangkh
 *
 */
public interface ServiceRepository {

	/**
     * 添加事件监听器
     * @param listener {@link ServiceListener}, 服务事件监听器
     */
    void addListener(ServiceListener listener);

    /**
     * 添加事件监听器和事件筛选器
     * @param listener {@link ServiceListener}, 服务事件监听器
     * @param filter {@link Filter}, 事件筛选器
     */
    void addListener(ServiceListener listener, Filter filter);

    /**
     * 添加服务事件监听器和事件过滤的条件
     * @param listener {@link ServiceListener}, 服务事件监听器
     * @param filterString {@link String}, 服务事件筛选字符串，用于筛选关注的服务.<br>
     * 			可以为null，表示监听所有服务事件
     */
    default void addListener(ServiceListener listener, String filterString){
        this.addListener(listener, this.createFilter(filterString));
    }

    /**
     * 使用筛选字符串创建筛选器<br>
     * 筛选字符串用于筛选关心的服务
     * @param filterString 筛选字符串,可以为null,为null表示不对事件进行过滤处理
     * @return {@link Filter}
     */
    Filter createFilter(String filterString);

    /**
     * 使用<code>serviceType</code>和<code>filterString</code>创建筛选器
     * @param serviceType {@link Class}，服务类型
     * @param filterString {@link String}, 筛选字符串
     * @return {@link Filter}
     */
    Filter createFilter(Class<?> serviceType, String filterString);

    /**
     * 按{@code serviceType}查找服务
     * @param serviceType {@link Class}, 服务类型
     * @param <S>
     * @return {@link Optional}
     */
    default <S> Optional<S> findService(Class<S> serviceType){
        return this.findService(serviceType, this.createFilter(null));
    }

    /**
     * 查找满足{@code filter}条件的首个服务
     * @param serviceType {@link Class}, 服务类型
     * @param filter {@link Filter}, 过滤器
     * @param <S>
     * @return {@link Optional}
     */
    <S> Optional<S> findService(Class<S> serviceType, Filter filter);

    /**
     * 查找满足{@code filterString}条件的首个服务
     * @param serviceType {@link Class}, 服务类型
     * @param filterString {@link String}, 过滤字符串
     * @param <S>
     * @return {@link Optional}
     */
    default <S> Optional<S> findService(Class<S> serviceType, String filterString){
        return this.findService(serviceType, this.createFilter(filterString));
    }


    /**
     * 根据{@code serviceType}查找服务引用
     * @param serviceType {@link Class}, 服务类型
     * @param <S>
     * @return {@link ServiceReference}, 可能返回null.
     */
    default <S> Optional<ServiceReference<S>> findServiceReference(Class<S> serviceType){
        return this.findServiceReference(serviceType, this.createFilter(null));
    }

    /**
     * 根据{@code sericeType}和{@code filterString}查找服务引用
     * @param serviceType  {@link Class},服务类型
     * @param filterString {@link String}, 过滤字符串
     * @param <S>
     * @return {@link ServiceReference}, 可能返回null.
     */
    default <S> Optional<ServiceReference<S>> findServiceReference(Class<S> serviceType, String filterString){
        return this.findServiceReference(serviceType, this.createFilter(filterString));
    }

    /**
     * 根据{@code serviceType}和{@code filter}查找服务引用
     * @param serviceType {@link Class},服务类型
     * @param filter {@link Filter},过滤条件
     * @param <S>
     * @return {@link Optional}.
     */
    <S> Optional<ServiceReference<S>> findServiceReference(Class<S> serviceType, Filter filter);

    /**
     * 获取类型为{@code serviceType}的服务.
     * <p>
     * 当服务未找到时，抛出例外
     * @param serviceType {@link Class},服务类型
     * @param <S> 服务类型
     * @return {@link S}, {@code action}的返回值，可能返回null.
     * @throws ServiceNotFoundException 服务不存在时抛出的例外
     */
    default <S> S getService(Class<S> serviceType) throws ServiceNotFoundException{
        return this.getService(serviceType, this.createFilter(null));
    }

    /**
     * 获取类型为{@code serviceType}并满足{@code filterString}的服务.
     * <p>
     * 当服务未找到时，抛出例外
     * @param serviceType {@link Class},服务类型
     * @param filterString 字符串形式的过滤条件
     * @param <S> 服务类型
     * @throws ServiceNotFoundException 服务不存在时抛出的例外
     */
    default <S> S getService(Class<S> serviceType, String filterString)
            throws ServiceNotFoundException{
        return this.getService(serviceType, this.createFilter(filterString));
    }

    /**
     * 获取类型为{@code serviceType}并满足{@code filter}的服务.
     * <p>
     * 当服务未找到时，抛出例外
     * @param serviceType {@link Class},服务类型
     * @param filter {@link Filter}, 过滤条件
     * @param <S> 服务类型
     * @throws ServiceNotFoundException 服务不存在时抛出的例外
     */
    <S> S getService(Class<S> serviceType, Filter filter) throws ServiceNotFoundException;

    /**
     * 所有{@code serviceType}类型的服务
     * @param serviceType {@link Class}, 服务类型
     * @param <S>
     * @return {@link List}
     */
    default <S> List<S> getServices(Class<S> serviceType){
        return this.getServices(serviceType, this.createFilter(null));
    }

    /**
     * 所有满足{@code filter}的{@code serviceType}类型的服务
     * @param serviceType {@link Class}, 服务类型
     * @param filter {@link Filter}, 过滤器
     * @param <S>
     * @return {@link List}
     */
    <S> List<S> getServices(Class<S> serviceType, Filter filter);

    /**
     * 所有满足{@code filterString}的{@code serviceType}类型的服务
     * @param serviceType {@link Class}, 服务类型
     * @param filterString {@link String}, 过滤字符串
     * @param <S>
     * @return {@link List}
     */
    default <S> List<S> getServices(Class<S> serviceType, String filterString){
        return this.getServices(serviceType, this.createFilter(filterString));
    }

    /**
     * 所有服务类型
     * @return {@link List}
     */
    List<Class<?>> getServiceTypes();

    /**
     * 使用{@code reference}定位服务，并使用
     * <p>
     * 可能因为服务同时被卸载，导致{@code reference}引用的服务不存在，这种情况下会抛出服务未找到例外
     * @param <S> 服务类型
     * @param reference {@link ServiceReference}, 服务引用
     * @return {@link Optional}
     */
    <S> Optional<S> getService(ServiceReference<S> reference);

    /**
     * 获取所有{@code serviceType}类型的服务，并使用
     * @param serviceType {@link Class},服务类型
     * @param <S> 服务类型
     * @return {@link List}, {@code action}的返回值，可能返回null.
     */
    default <S> List<ServiceReference<S>> getServiceReferences(Class<S> serviceType){
        return this.getServiceReferences(serviceType, this.createFilter(null));
    }

    /**
     * 获取{@code serviceType}类型并满足{@code filterString}条件的所有服务引用
     * @param serviceType {@link Class},服务类型
     * @param filterString 字符串形式的过滤条件
     * @param <S> 服务类型
     * @return {@link List}
     */
   default <S> List<ServiceReference<S>> getServiceReferences(Class<S> serviceType, String filterString){
       return this.getServiceReferences(serviceType, this.createFilter(filterString));
   }

    /**
     * 获取{@code serviceType}类型并满足{@code filterString}条件的所有服务引用
     * @param serviceType {@link Class},服务类型
     * @param filter 过滤条件
     * @param <S> 服务类型
     * @return {@link List}.
     */
    <S> List<ServiceReference<S>> getServiceReferences(Class<S> serviceType, Filter filter);

    /**
     * 获取满足{@code filterString}的所有服务引用
     * @param filterString {@link String},字符串形式的过滤条件
     * @return {@link List}
     */
    default List<ServiceReference<?>> getServiceReferences(String filterString){
        Objects.requireNonNull(filterString, "\"filterString\" cannot be null.");
        return this.getServiceReferences(this.createFilter(filterString));
    }

    /**
     * 获取满足{@code filter}的所有服务引用
     * @param filter {@link Filter},过滤条件
     * @return {@link List}
     */
    List<ServiceReference<?>> getServiceReferences(Filter filter);

    /**
     * 服务注册器
     * @return {@link ServiceRegistry}
     */
    ServiceRegistry getServiceRegistry();

    /**
     * 移除事件监听器
     * @param listener {@link ServiceListener}, 服务事件监听器
     */
    void removeListener(ServiceListener listener);

    /**
     * 从{@code module}取回服务仓储
     * @param module {@link Module},模块
     * @return {@link ServiceRepository}
     */
    static ServiceRepository retrieveFrom(Module<?> module) {
        Objects.requireNonNull(module, "\"module\" cannot be null.");
        return module.adapt(ServiceRepository.class);
    }
}
